1   /*
2    * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package com.sun.nio.sctp;
26  
27  import java.net.SocketAddress;
28  import sun.nio.ch.SctpStdSocketOption;
29  
30  /**
31   * SCTP channels supports the socket options defined by this class
32   * (as well as those listed in the particular channel class) and may support
33   * additional Implementation specific socket options.
34   *
35   * @since 1.7
36   */
37  public class SctpStandardSocketOptions {
38      private SctpStandardSocketOptions() {}
39      /**
40       * Enables or disables message fragmentation.
41       *
42       * <P> The value of this socket option is a {@code Boolean} that represents
43       * whether the option is enabled or disabled. If enabled no SCTP message
44       * fragmentation will be performed. Instead if a message being sent
45       * exceeds the current PMTU size, the message will NOT be sent and
46       * an error will be indicated to the user.
47       *
48       * <P> It is implementation specific whether or not this option is
49       * supported.
50       */
51      public static final SctpSocketOption<Boolean> SCTP_DISABLE_FRAGMENTS = new
52          SctpStdSocketOption<Boolean>("SCTP_DISABLE_FRAGMENTS", Boolean.class,
53          sun.nio.ch.SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS);
54  
55      /**
56       * Enables or disables explicit message completion.
57       *
58       * <p> The value of this socket option is a {@code Boolean} that represents
59       * whether the option is enabled or disabled. When this option is enabled,
60       * the {@code send} method may be invoked multiple times to a send message.
61       * The {@code isComplete} parameter of the {@link MessageInfo} must only
62       * be set to {@code true} for the final send to indicate that the message is
63       * complete. If this option is disabled then each individual {@code send}
64       * invocation is considered complete.
65       *
66       * <P> The default value of the option is {@code false} indicating that the
67       * option is disabled. It is implementation specific whether or not this
68       * option is supported.
69       */
70      public static final SctpSocketOption<Boolean> SCTP_EXPLICIT_COMPLETE = new
71          SctpStdSocketOption<Boolean>("SCTP_EXPLICIT_COMPLETE", Boolean.class,
72          sun.nio.ch.SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE);
73  
74      /**
75       * Fragmented interleave controls how the presentation of messages occur
76       * for the message receiver. There are three levels of fragment interleave
77       * defined. Two of the levels effect {@link SctpChannel}, while
78       * {@link SctpMultiChannel} is effected by all three levels.
79       *
80       * <P> This option takes an {@code Integer} value. It can be set to a value
81       * of {@code 0}, {@code 1} or {@code 2}.
82       *
83       * <P> Setting the three levels provides the following receiver
84       * interactions:
85       *
86       * <P> {@code level 0} - Prevents the interleaving of any messages. This
87       * means that when a partial delivery begins, no other messages will be
88       * received except the message being partially delivered. If another message
89       * arrives on a different stream (or association) that could be delivered,
90       * it will be blocked waiting for the user to read all of the partially
91       * delivered message.
92       *
93       * <P> {@code level 1} - Allows interleaving of messages that are from
94       * different associations. For {@code SctpChannel}, level 0 and
95       * level 1 have the same meaning since an {@code SctpChannel} always
96       * receives messages from the same association. Note that setting an {@code
97       * SctpMultiChannel} to this level may cause multiple partial
98       * delivers from different associations but for any given association, only
99       * one message will be delivered until all parts of a message have been
100      * delivered. This means that one large message, being read with an
101      * association identification of "X", will block other messages from
102      * association "X" from being delivered.
103      *
104      * <P> {@code level 2} - Allows complete interleaving of messages. This
105      * level requires that the sender carefully observe not only the peer
106      * {@code Association} but also must pay careful attention to the stream
107      * number. With this option enabled a partially delivered message may begin
108      * being delivered for association "X" stream "Y" and the next subsequent
109      * receive may return a message from association "X" stream "Z". Note that
110      * no other messages would be delivered for association "X" stream "Y"
111      * until all of stream "Y"'s partially delivered message was read.
112      * Note that this option effects both channel types.  Also note that
113      * for an {@code SctpMultiChannel} not only may another streams
114      * message from the same association be delivered from the next receive,
115      * some other associations message may be delivered upon the next receive.
116      *
117      * <P> It is implementation specific whether or not this option is
118      * supported.
119      */
120     public static final SctpSocketOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
121             new SctpStdSocketOption<Integer>("SCTP_FRAGMENT_INTERLEAVE",
122                   Integer.class,
123                   sun.nio.ch.SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE);
124 
125     /**
126      * The maximum number of streams requested by the local endpoint during
127      * association initialization.
128      *
129      * <P> The value of this socket option is an {@link
130      * SctpStandardSocketOptions.InitMaxStreams InitMaxStreams}, that represents
131      * the maximum number of inbound and outbound streams that an association
132      * on the channel is prepared to support.
133      *
134      * <P> For an {@link SctpChannel} this option may only be used to
135      * change the number of inbound/outbound streams prior to connecting.
136      *
137      * <P> For an {@link SctpMultiChannel} this option determines
138      * the maximum number of inbound/outbound streams new associations setup
139      * on the channel will be prepared to support.
140      *
141      * <P> For an {@link SctpServerChannel} this option determines the
142      * maximum number of inbound/outbound streams accepted sockets will
143      * negotiate with their connecting peer.
144      *
145      * <P> In all cases the value set by this option is used in the negotiation
146      * of new associations setup on the channel's socket and the actual
147      * maximum number of inbound/outbound streams that have been negotiated
148      * with the peer can be retrieved from the appropriate {@link
149      * Association}. The {@code Association} can be retrieved from the
150      * {@link AssociationChangeNotification.AssocChangeEvent#COMM_UP COMM_UP}
151      * {@link AssociationChangeNotification} belonging to that association.
152      *
153      * <p> This value is bounded by the actual implementation. In other
154      * words the user may be able to support more streams than the Operating
155      * System. In such a case, the Operating System limit may override the
156      * value requested by the user. The default value of 0 indicates to use
157      * the endpoints default value.
158      */
159     public static final SctpSocketOption
160         <SctpStandardSocketOptions.InitMaxStreams> SCTP_INIT_MAXSTREAMS =
161         new SctpStdSocketOption<SctpStandardSocketOptions.InitMaxStreams>(
162         "SCTP_INIT_MAXSTREAMS", SctpStandardSocketOptions.InitMaxStreams.class);
163 
164     /**
165      * Enables or disables a Nagle-like algorithm.
166      *
167      * <P> The value of this socket option is a {@code Boolean} that represents
168      * whether the option is enabled or disabled. SCTP uses an algorithm like
169      * <em>The Nagle Algorithm</em> to coalesce short segments and
170      * improve network efficiency.
171      */
172     public static final SctpSocketOption<Boolean> SCTP_NODELAY =
173         new SctpStdSocketOption<Boolean>("SCTP_NODELAY", Boolean.class,
174         sun.nio.ch.SctpStdSocketOption.SCTP_NODELAY);
175 
176     /**
177      * Requests that the local SCTP stack use the given peer address as
178      * the association primary.
179      *
180      * <P> The value of this socket option is a {@code SocketAddress}
181      * that represents the peer address that the local SCTP stack should use as
182      * the association primary. The address must be one of the association
183      * peer's addresses.
184      *
185      * <P> An {@code SctpMultiChannel} can control more than one
186      * association, the association parameter must be given when setting or
187      * retrieving this option.
188      *
189      * <P> Since {@code SctpChannel} only controls one association,
190      * the association parameter is not required and this option can be
191      * set or queried directly.
192      */
193      public static final SctpSocketOption<SocketAddress> SCTP_PRIMARY_ADDR =
194              new SctpStdSocketOption<SocketAddress>
195              ("SCTP_PRIMARY_ADDR", SocketAddress.class);
196 
197      /**
198      * Requests that the peer mark the enclosed address as the association
199      * primary.
200      *
201      * <P> The value of this socket option is a {@code SocketAddress}
202      * that represents the local address that the peer should use as its
203      * primary address. The given address must be one of the association's
204      * locally bound addresses.
205      *
206      * <P> An {@code SctpMultiChannel} can control more than one
207      * association, the association parameter must be given when setting or
208      * retrieving this option.
209      *
210      * <P> Since {@code SctpChannel} only controls one association,
211      * the association parameter is not required and this option can be
212      * queried directly.
213      *
214      * <P> Note, this is a set only option and cannot be retrieved by {@code
215      * getOption}. It is implementation specific whether or not this
216      * option is supported.
217      */
218     public static final SctpSocketOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
219             new SctpStdSocketOption<SocketAddress>
220             ("SCTP_SET_PEER_PRIMARY_ADDR", SocketAddress.class);
221 
222     /**
223      * The size of the socket send buffer.
224      *
225      * <p> The value of this socket option is an {@code Integer} that is the
226      * size of the socket send buffer in bytes. The socket send buffer is an
227      * output buffer used by the networking implementation. It may need to be
228      * increased for high-volume connections. The value of the socket option is
229      * a <em>hint</em> to the implementation to size the buffer and the actual
230      * size may differ. The socket option can be queried to retrieve the actual
231      * size.
232      *
233      * <p> For {@code SctpChannel}, this controls the amount of data
234      * the SCTP stack may have waiting in internal buffers to be sent. This
235      * option therefore bounds the maximum size of data that can be sent in a
236      * single send call.
237      *
238      * <P> For {@code SctpMultiChannel}, the effect is the same as for {@code
239      * SctpChannel}, except that it applies to all associations. The option
240      * applies to each association's window size separately.
241      *
242      * <p> An implementation allows this socket option to be set before the
243      * socket is bound or connected. Whether an implementation allows the
244      * socket send buffer to be changed after the socket is bound is system
245      * dependent.
246      */
247     public static final SctpSocketOption<Integer> SO_SNDBUF =
248         new SctpStdSocketOption<Integer>("SO_SNDBUF", Integer.class,
249         sun.nio.ch.SctpStdSocketOption.SO_SNDBUF);
250 
251     /**
252      * The size of the socket receive buffer.
253      *
254      * <P> The value of this socket option is an {@code Integer} that is the
255      * size of the socket receive buffer in bytes. The socket receive buffer is
256      * an input buffer used by the networking implementation. It may need to be
257      * increased for high-volume connections or decreased to limit the possible
258      * backlog of incoming data. The value of the socket option is a
259      * <em>hint</em> to the implementation to size the buffer and the actual
260      * size may differ.
261      *
262      * <P> For {@code SctpChannel}, this controls the receiver window size.
263      *
264      * <P> For {@code SctpMultiChannel}, the meaning is implementation
265      * dependent. It might control the receive buffer for each association bound
266      * to the socket descriptor or it might control the receive buffer for the
267      * whole socket.
268      *
269      * <p> An implementation allows this socket option to be set before the
270      * socket is bound or connected. Whether an implementation allows the
271      * socket receive buffer to be changed after the socket is bound is system
272      * dependent.
273      */
274     public static final SctpSocketOption<Integer> SO_RCVBUF =
275         new SctpStdSocketOption<Integer>("SO_RCVBUF", Integer.class,
276         sun.nio.ch.SctpStdSocketOption.SO_RCVBUF);
277 
278     /**
279      * Linger on close if data is present.
280      *
281      * <p> The value of this socket option is an {@code Integer} that controls
282      * the action taken when unsent data is queued on the socket and a method
283      * to close the socket is invoked. If the value of the socket option is zero
284      * or greater, then it represents a timeout value, in seconds, known as the
285      * <em>linger interval</em>. The linger interval is the timeout for the
286      * {@code close} method to block while the operating system attempts to
287      * transmit the unsent data or it decides that it is unable to transmit the
288      * data. If the value of the socket option is less than zero then the option
289      * is disabled. In that case the {@code close} method does not wait until
290      * unsent data is transmitted; if possible the operating system will transmit
291      * any unsent data before the connection is closed.
292      *
293      * <p> This socket option is intended for use with sockets that are configured
294      * in {@link java.nio.channels.SelectableChannel#isBlocking() blocking} mode
295      * only. The behavior of the {@code close} method when this option is
296      * enabled on a non-blocking socket is not defined.
297      *
298      * <p> The initial value of this socket option is a negative value, meaning
299      * that the option is disabled. The option may be enabled, or the linger
300      * interval changed, at any time. The maximum value of the linger interval
301      * is system dependent. Setting the linger interval to a value that is
302      * greater than its maximum value causes the linger interval to be set to
303      * its maximum value.
304      */
305     public static final SctpSocketOption<Integer> SO_LINGER =
306         new SctpStdSocketOption<Integer>("SO_LINGER", Integer.class,
307         sun.nio.ch.SctpStdSocketOption.SO_LINGER);
308 
309     /**
310      * This class is used to set the maximum number of inbound/outbound streams
311      * used by the local endpoint during association initialization. An
312      * instance of this class is used to set the {@link
313      * SctpStandardSocketOptions#SCTP_INIT_MAXSTREAMS SCTP_INIT_MAXSTREAMS}
314      * socket option.
315      *
316      * @since 1.7
317      */
318     public static class InitMaxStreams {
319         private int maxInStreams;
320         private int maxOutStreams;
321 
322         private InitMaxStreams(int maxInStreams, int maxOutStreams) {
323            this.maxInStreams = maxInStreams;
324            this.maxOutStreams = maxOutStreams;
325         }
326 
327         /**
328          * Creates an InitMaxStreams instance.
329          *
330          * @param  maxInStreams
331          *         The maximum number of inbound streams, where
332          *         {@code 0 <= maxInStreams <= 65536}
333          *
334          * @param  maxOutStreams
335          *         The maximum number of outbound streams, where
336          *         {@code 0 <= maxOutStreams <= 65536}
337          *
338          * @return  An {@code InitMaxStreams} instance
339          *
340          * @throws  IllegalArgumentException
341          *          If an argument is outside of specified bounds
342          */
343         public static InitMaxStreams create
344               (int maxInStreams, int maxOutStreams) {
345             if (maxOutStreams < 0 || maxOutStreams > 65535)
346                 throw new IllegalArgumentException(
347                       "Invalid maxOutStreams value");
348             if (maxInStreams < 0 || maxInStreams > 65535)
349                 throw new IllegalArgumentException(
350                       "Invalid maxInStreams value");
351 
352             return new InitMaxStreams(maxInStreams, maxOutStreams);
353         }
354 
355         /**
356          * Returns the maximum number of inbound streams.
357          *
358          * @return  Maximum inbound streams
359          */
360         public int maxInStreams() {
361             return maxInStreams;
362         }
363 
364         /**
365          * Returns the maximum number of outbound streams.
366          *
367          * @return  Maximum outbound streams
368          */
369         public int maxOutStreams() {
370             return maxOutStreams;
371         }
372 
373         /**
374          * Returns a string representation of this init max streams, including
375          * the maximum in and out bound streams.
376          *
377          * @return  A string representation of this init max streams
378          */
379         @Override
380         public String toString() {
381             StringBuilder sb = new StringBuilder();
382             sb.append(super.toString()).append(" [");
383             sb.append("maxInStreams:").append(maxInStreams);
384             sb.append("maxOutStreams:").append(maxOutStreams).append("]");
385             return sb.toString();
386         }
387 
388         /**
389          * Returns true if the specified object is another {@code InitMaxStreams}
390          * instance with the same number of in and out bound streams.
391          *
392          * @param  obj
393          *         The object to be compared with this init max streams
394          *
395          * @return  true if the specified object is another
396          *          {@code InitMaxStreams} instance with the same number of in
397          *          and out bound streams
398          */
399         @Override
400         public boolean equals(Object obj) {
401             if (obj != null && obj instanceof InitMaxStreams) {
402                 InitMaxStreams that = (InitMaxStreams) obj;
403                 if (this.maxInStreams == that.maxInStreams &&
404                     this.maxOutStreams == that.maxOutStreams)
405                     return true;
406             }
407             return false;
408         }
409 
410         /**
411          * Returns a hash code value for this init max streams.
412          */
413         @Override
414         public int hashCode() {
415             int hash = 7 ^ maxInStreams ^ maxOutStreams;
416             return hash;
417         }
418     }
419 }